using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

namespace RexToy.Json
{
    public class JsonObject
    {
        private Hashtable table;

        public JsonObject()
        {
            table = new Hashtable();
        }

        public void AddKVPair(string key, object val)
        {
            table.Add(key, val);
        }

        public object this[string key]
        {
            get
            {
                if (table.ContainsKey(key))
                    return table[key];
                else
                    return null;
            }
        }

        public object Render(Type type, bool ignoreTypeSafe)
        {
            if (!type.HasDefaultConstructor())
                ExceptionHelper.ThrowNoDefaultConstructor(type);

            object instance = Activator.CreateInstance(type, true);
            IReflector r = Reflector.Bind(instance, ReflectorPolicy.InstancePublicIgnoreCase);
            foreach (DictionaryEntry de in table)
            {
                string propertyName = (string)de.Key;

                if (de.Value == null)
                {
                    r.SetPropertyValue(propertyName, null);
                    continue;
                }

                JsonObject innerJson = de.Value as JsonObject;
                if (innerJson != null)
                {
                    Type innerType = r.GetPropertyType(propertyName);
                    object inner = innerJson.Render(innerType, ignoreTypeSafe);
                    r.SetPropertyValue(propertyName, inner);
                    continue;
                }

                JsonArray innerArray = de.Value as JsonArray;
                if (innerArray != null)
                {
                    Type elementType = r.GetPropertyType(propertyName).GetElementType();
                    Array array = innerArray.Render(elementType, ignoreTypeSafe);
                    r.SetPropertyValue(propertyName, array);
                    continue;
                }

                object val = JsonExtension.ConvertToSimpleType((string)de.Value, r.GetPropertyType(propertyName), ignoreTypeSafe);
                r.SetPropertyValue(propertyName, val);
            }

            return instance;
        }

        public T Render<T>(bool ignoreTypeSafe)
        {
            return (T)this.Render(typeof(T), ignoreTypeSafe);
        }
    }
}